package com.leyou.item.service;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.leyou.common.constants.MQConstants;
import com.leyou.common.exception.pojo.ExceptionEnum;
import com.leyou.common.exception.pojo.LyException;
import com.leyou.common.pojo.PageResult;
import com.leyou.common.utils.BeanHelper;
import com.leyou.item.dto.SpuDTO;
import com.leyou.item.mapper.SkuMapper;
import com.leyou.item.mapper.SpuDetailMapper;
import com.leyou.item.mapper.SpuMapper;
import com.leyou.item.pojo.*;
import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.sql.Wrapper;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 商品业务
 */
@Service
@Transactional
public class GoodsService extends ServiceImpl<SkuMapper,Sku> {
    @Autowired
    private SpuMapper spuMapper;
    @Autowired
    private SpuDetailMapper spuDetailMapper;
    @Autowired
    private SkuMapper skuMapper;
    @Autowired
    private BrandService brandService;
    @Autowired
    private CategoryService categoryService;

    @Autowired
    private RocketMQTemplate rocketMQTemplate;


    public PageResult<SpuDTO> spuPageQuery(Integer page, Integer rows, String key, Boolean saleable) {
        //1.封装条件
        //1）封装分页参数
        IPage<Spu> iPage = new Page<>(page,rows);

        //2）封装查询条件
        QueryWrapper<Spu> query = Wrappers.query();

        //处理key
        if(StringUtils.isNotEmpty(key)){
            //注意：如果希望把一些条件的优先级提高（在条件外面 加括号），使用and()方法组合条件，这里必须是Lambda表达式
            query.and( i -> i.like("name",key)
                    .or()
                    .like("sub_title",key)
            );
        }

        //处理saleable
        if(saleable!=null){
            query.eq("saleable",saleable); //注意：不需要把saleable转换为1或0，因为MyBatisPlus底层自动把true转换为1，false转换为0
        }

        //2.执行查询，获取结果
        iPage = spuMapper.selectPage(iPage,query);

        //3.处理结果，返回
        //1）取出Spu结果
        List<Spu> spuList = iPage.getRecords();
        //2）把Spu对象的属性拷贝到SpuDTO对象上
        List<SpuDTO> spuDTOList = BeanHelper.copyWithCollection(spuList, SpuDTO.class);
        //3）查询分类名称和品牌名称
        findCategoryNameAndBrandName(spuDTOList);
        //4）封装PageResult
        PageResult<SpuDTO> pageResult = new PageResult<>(iPage.getTotal(),iPage.getPages(),spuDTOList);
        return pageResult;
    }

    /**
     * 查询分类名称和品牌名称
     * @param spuDTOList
     */
    private void findCategoryNameAndBrandName(List<SpuDTO> spuDTOList) {
        spuDTOList.forEach(spuDTO -> {
            //1.根据ID查询品牌
            Brand brand = brandService.findBrandById(spuDTO.getBrandId());
            spuDTO.setBrandName(brand.getName());

            //2.查询分类名称
            List<Category> categoryList = categoryService.findCategoriesByIds(
                    Arrays.asList(spuDTO.getCid1(), spuDTO.getCid2(), spuDTO.getCid3()));
            //格式：手机通讯/手机/手机
            //使用JDK1.8新特性：流式编程
            String categoryName = categoryList.stream()
                                        .map(category -> category.getName())
                                        .collect(Collectors.joining("/"));
            spuDTO.setCategoryName(categoryName);
        });
    }

    public void saveGoods(SpuDTO spuDTO) {
        try {
            //1.保存Spu表
            //把SpuDTO数据拷贝到Spu对象
            Spu spu = BeanHelper.copyProperties(spuDTO, Spu.class);
            //默认状态为下架
            spu.setSaleable(false);
            spuMapper.insert(spu);

            //2.保存SpuDetail表
            SpuDetail spuDetail = spuDTO.getSpuDetail();
            //设置spu的id
            spuDetail.setSpuId(spu.getId());
            spuDetailMapper.insert(spuDetail);

            //3.保存Sku表
            List<Sku> skus = spuDTO.getSkus();
            //设置spu的id
            skus.forEach(sku->{
                sku.setSpuId(spu.getId());
            });
            //批量保存
            saveBatch(skus);//注意：saveBatch方法继承自ServiceImpl类
        } catch (Exception e) {
            e.printStackTrace();
            throw new LyException(ExceptionEnum.INSERT_OPERATION_FAIL);
        }
    }

    public void updateSaleable(Long id, Boolean saleable) {
        try {
            Spu spu = new Spu();
            spu.setId(id);
            spu.setSaleable(saleable);
            spuMapper.updateById(spu);

            //发现消息给MQ（MQ通知消费进行索引库和静态页操作）
            /**
             * 参数一：消息目的地（如果只有主题，写主题名即可，但是如果既有主题，也有标签，那么写  "主题名:标签名"  ）
             * 参数二：消息内容
             */
            //定义标签
            String tagName = saleable?MQConstants.Tag.ITEM_UP_TAG:MQConstants.Tag.ITEM_DOWN_TAG;
            //定义目的地
            String destination = MQConstants.Topic.ITEM_TOPIC_NAME+":"+tagName;
            //发送消息
            rocketMQTemplate.convertAndSend(destination,id);
        } catch (Exception e) {
            e.printStackTrace();
            throw new LyException(ExceptionEnum.UPDATE_OPERATION_FAIL);
        }
    }

    public List<Sku> findSkusBySpuId(Long id) {
        //1.封装条件
        QueryWrapper<Sku> query = Wrappers.query();
        query.eq("spu_id",id);
        //2.查询
        List<Sku> skus = skuMapper.selectList(query);
        //3.返回
        return skus;
    }


    public SpuDetail findSpuDetailBySpuId(Long id) {
        SpuDetail spuDetail = spuDetailMapper.selectById(id);
        if(spuDetail==null){
            throw new LyException(ExceptionEnum.GOODS_NOT_FOUND);
        }
        return spuDetail;
    }

    public SpuDTO findSpuById(Long id) {
        //1.查询Spu对象
        Spu spu = spuMapper.selectById(id);
        //2.拷贝数据
        SpuDTO spuDTO = BeanHelper.copyProperties(spu, SpuDTO.class);
        //3.封装List<Sku>
        List<Sku> skuList = findSkusBySpuId(id);
        spuDTO.setSkus(skuList);
        //4.封装SpuDetail
        SpuDetail detail = findSpuDetailBySpuId(id);
        spuDTO.setSpuDetail(detail);
        return spuDTO;
    }
}
